package lion.formail.reader.reader.v4;

import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import lion.dev.io.FileUtil;
import lion.formail.reader.obj.Idx;
import lion.formail.reader.reader.IReader;
import lion.formail.reader.util.Util;

/**
 * foxmail version under 5
 * 
 * @author lion
 * @email hl_0074@sina.com
 * @date 2014年4月29日
 */
public class IndReader implements IReader {

	@Override
	public int countEmls(boolean countDeleted, File file) throws IOException {

		if (!file.getName().toLowerCase().endsWith("ind")) { throw new IllegalArgumentException("the file must be foxmail's 'ind' file and the filename should be end with 'IND'"); }

		// 头部64
		int header = 0x40;
		int count = 0;

		// 176为一个索引内容
		byte[] content = new byte[0xb0];

		DataInputStream dis = null;

		try {

			dis = new DataInputStream(new FileInputStream(file));
			// 跳过头部
			dis.skip(header);

			while ((dis.read(content) != -1)) {
				if (content[0x04] == 0 || (content[0x04] == 1 && countDeleted)) {
					count++;
				}
			}
		} catch (IOException e) {
			throw e;
		} finally {
			if (dis != null) {
				dis.close();
			}
		}
		return count;
	}

	@Override
	public List<Idx> getIndexList(boolean countDeleted, File file) throws IOException {

		if (!file.getName().toLowerCase().endsWith("ind")) { throw new IllegalArgumentException("the file must be foxmail's 'IND' file and the filename should be end with 'IND'"); }
		int header = 0x40;
		List<Idx> indexList = new ArrayList<Idx>();
		byte[] content = new byte[0xb0];
		DataInputStream dis = null;
		try {
			dis = new DataInputStream(new FileInputStream(file));
			dis.skip(header);
			while (dis.read(content) != -1) {
				if (content[0x04] == 1 && !countDeleted) {
					continue;
				}
				Idx index = getIndexInfoFromByteArray(content);
				indexList.add(index);
			}
		} catch (IOException e) {
			throw e;
		} finally {
			if (dis != null) {
				dis.close();
			}
		}
		return indexList;
	}

	public Idx getIndexInfoFromByteArray(byte[] content) {

		Idx index = new Idx();
		fillBasicData(content, index);
		/**
		 * 收信日期 0x14 -0x1b 未取到， <br>
		 * 1,主要是Delphi的时间与Java的时间之间的转换。<br>
		 * 2,Foxmail中以8个字节表示时间，这8个字节如何转换为Delphi的时间
		 */

		// 0x21 sender
		int offset = 0x21;
		byte[] buf = new byte[0x80]; // 128b
		int i = 0;
		i = fillByteArray(content, offset, buf);
		offset += i;
		index.setSender(new String(buf, 0, i));

		// subject
		buf = new byte[0xb0 - offset];
		offset = offset + 1;
		i = fillByteArray(content, offset, buf);
		offset += i;

		index.setSubject(FileUtil.read(Arrays.copyOfRange(buf, 0, i + 1)));

		return index;
	}

	public void fillBasicData(byte[] content, Idx index) {

		// Index 1-4
		int[] bt = new int[0x04];
		for (int i = 0; i < 0x04; i++) {
			bt[i] = content[0x03 - i];
		}
		index.setIndex(Integer.decode(Util.byteArrayToHexString(bt)).intValue()); // 0x03

		// isDelete
		if (content[4] == 1) { // 0x04
			index.setDelete(true);
		}

		// offSet
		bt = new int[4];
		for (int i = 0; i < 4; i++) {
			bt[i] = content[8 - i];
		}
		index.setOffSet(Integer.decode(Util.byteArrayToHexString(bt)).intValue()); // 0x05-0x08

		// size
		bt = new int[4];
		for (int i = 0; i < 4; i++) {
			bt[i] = content[12 - i];
		}
		index.setSize(Integer.decode(Util.byteArrayToHexString(bt)).intValue()); // 0x09-0x0d

		// isReadAlready
		if (content[0x12] == 0) {
			index.setReadAlready(true); // 0x12
		}

		// hasAttachement
		if (content[0x13] == 1) {
			index.setHasAttachment(true); // 0x13
		}

	}

	public int fillByteArray(byte[] content, int offset, byte[] buf) {

		int i = 0;
		for (i = 0;; i++) {
			if (content[offset + i] == 0) {
				break;
			}
			buf[i] = content[offset + i];
		}
		return i;
	}

	@Override
	public byte[] getEmlContent(Idx index, File boxFile) throws IOException {

		if (!boxFile.exists()) { throw new FileNotFoundException(boxFile.getAbsolutePath() + " is not found"); }
		if (!boxFile.getName().toLowerCase().endsWith("box")) { throw new IllegalArgumentException(
				"the file must be foxmail's 'box' file and the filename should be end with 'box'"); }
		byte[] content = new byte[index.getSize()];
		FileInputStream fis = null;
		try {
			fis = new FileInputStream(boxFile);
			fis.skip(index.getOffSet());
			fis.read(content);
		} catch (IOException ex) {
			throw ex;
		} finally {
			if (fis != null) {
				fis.close();
			}
		}
		return content;
	}

	@Override
	public void export(Idx idx, File boxFile, File destFile) throws IOException {

		String filePath = destFile.getAbsolutePath();
		if (destFile.isDirectory()) {
			if (idx.getSubject() != null) {
				filePath = filePath + "/" + idx.getSubject();
			} else if (idx.getSender() != null) {
				filePath = filePath + "/" + idx.getSender();
			} else {
				filePath = filePath + "/" + String.valueOf(idx.getIndex());
			}
			filePath += ".eml";
		} else {
			filePath = destFile.getAbsolutePath().toLowerCase().endsWith("eml") ? destFile.getAbsolutePath() : destFile.getAbsolutePath() + ".eml";
		}
		byte[] content = getEmlContent(idx, boxFile);
		write(content, filePath);
	}

	public void write(byte[] content, String destPath) throws IOException {

		FileOutputStream fos = null;
		try {
			fos = new FileOutputStream(new File(destPath));
			fos.write(content);
			fos.flush();
		} catch (IOException e) {
			throw e;
		} finally {
			if (fos != null) {
				fos.close();
			}
		}
	}

}
